package org.jpropelleralt.ledger.impl;

import org.jpropelleralt.change.Change;
import org.jpropelleralt.ledger.LedgerChange;

/**
 * Immutable implementation of {@link LedgerChange} 
 */
public class LedgerChangeDefault implements LedgerChange {

	private final boolean shallow;
	private final boolean columnsChanged;
	private final boolean rowCountChanged;

	/**
	 * Make a new {@link LedgerChangeDefault}
	 * @param shallow 	True if any instance in the list's data 
	 * 					is different after the change
	 * @param columnsChanged	True if column names/classes have changed
	 * @param rowCountChanged	True if the row count has changed
	 */
	public LedgerChangeDefault(boolean shallow, boolean columnsChanged, boolean rowCountChanged) {
		super();
		this.shallow = shallow;
		this.columnsChanged = columnsChanged;
		this.rowCountChanged = rowCountChanged;
	}
	
	@Override
	public Change extend(Change existing) {
		
		if (!(existing instanceof LedgerChange)) {
			throw new IllegalArgumentException("A ListChange can only extend another Listchange");
		}
		
		LedgerChange ledgerExisting = (LedgerChange)existing;
		
		//Extend different aspects of the change
		boolean extendsShallow = shallow() || existing.shallow();
		boolean extendsColumnsChanged = columnsChanged() || ledgerExisting.columnsChanged();
		boolean extendsRowCountChanged = rowCountChanged() || ledgerExisting.rowCountChanged();

		return new LedgerChangeDefault(extendsShallow, extendsColumnsChanged, extendsRowCountChanged);
	}

	@Override
	public boolean shallow() {
		return shallow;
	}

	@Override
	public String toString() {
		return (shallow ? "Shallow ":"Deep ") + "Ledger Change." + 
				(columnsChanged() ? " Columns changed." : "") + 
				(rowCountChanged() ? " Row Count changed." : "");
	}

	@Override
	public boolean columnsChanged() {
		return columnsChanged;
	}

	@Override
	public boolean rowCountChanged() {
		return rowCountChanged;
	}
}
